//
// Created by Cybaster on 2024/3/30.
//

#include "image_stitch.h"
#include "helper.h"
#include <iostream>
#include <string>
#include <vector>


using namespace std;
using namespace stitch;


int main(int argc, char **argv) {

    string img1Path, img2Path;

    if (argc != 3) {
        cerr << "Usage: <path to 1st image> <path to 2nd image>" << endl;
        cerr << "Press enter to continue..." << endl;
        cin.get();
        return -1;
    } else {
        img1Path = argv[1];
        img2Path = argv[2];
    }

    cv::Mat fstImage = cv::imread(img1Path);
    cv::Mat sndImage = cv::imread(img2Path);

    if ((!fstImage.data) || (!sndImage.data)) {
        cerr << "ERROR: Could not load images" << endl;
        cerr << "Press enter to continue..." << endl;
        cin.get();
        exit(-2);
    }

    std::vector<cv::Vec3f> p_fst, p_snd;
    getRawPointsAutomatic(fstImage, sndImage, p_fst, p_snd);

    cout << "Number of raw defined point pairs: " << p_fst.size() << endl;

    cout << "Press enter to continue..." << endl;
    cin.get();

    getPointsAutomatic(fstImage, sndImage, p_fst, p_snd);

    cout << "Number of defined point pairs: " << p_fst.size() << endl;

    const float inlierThreshold = 2.0f;

    std::cout << "=== Direct estimation: ===" << std::endl;

    {
        cv::Matx33f F = getFundamentalMatrix(p_fst, p_snd);

        float err = getError(p_fst, p_snd, F);
        cout << "Geometric error: " << err << endl;
        unsigned numInlier = countInliers(p_fst, p_snd, F, inlierThreshold);
        cout << "Number of inliers: " << numInlier << " of " << p_fst.size() << endl;

        visualize(fstImage, sndImage, p_fst, p_snd, F);
    }

    std::cout << "=== Robust estimation: ===" << std::endl;

    {
        cv::Matx33f F = estimateFundamentalRANSAC(p_fst, p_snd, 10000, inlierThreshold);

        float err = getError(p_fst, p_snd, F);
        cout << "Geometric error: " << err << endl;
        unsigned numInlier = countInliers(p_fst, p_snd, F, inlierThreshold);
        cout << "Number of inliers: " << numInlier << " of " << p_fst.size() << endl;

        visualize(fstImage, sndImage, p_fst, p_snd, F);
    }

    const char *matchesWindowName = "matches";

    cv::Mat matchesImage = drawMatches(fstImage, sndImage, p_fst, p_snd);
    cv::namedWindow(matchesWindowName, 0);
    cv::imshow(matchesWindowName, matchesImage);
    cv::waitKey(0);
    cv::destroyWindow(matchesWindowName);
    cv::imwrite("matches.png", matchesImage);

    cv::Matx33f H = stitch::homography2D(p_fst, p_snd);

    cv::Mat panorama = stitch::stitch(fstImage, sndImage, H);

    const char *panoramaWindowName = "Panorama";

    cv::namedWindow(panoramaWindowName, 0);
    cv::imshow(panoramaWindowName, panorama);
    cv::waitKey(0);
    cv::destroyWindow(panoramaWindowName);

    cv::imwrite("panorama.png", panorama);


    return 0;

}
